#
# Copyright 2009 Red Hat, Inc. and/or its affiliates.
#
# Licensed to you under the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.  See the files README and
# LICENSE_GPL_v2 which accompany this distribution.
#

import threading
import rwlock


class SyncSpace(object):
    def __init__(self, name):
        self.name = name
        self.objects = {}
        self.lock = threading.Lock()

    def getObj(self, objname):
        objname = str(objname)
        self.lock.acquire()
        o = self.objects.get(objname, None)
        if not o:
            o = self.objects[objname] = [rwlock.RWLock(), 1]
        else:
            o[1] += 1
        self.lock.release()
        return o

    def putObj(self, objname):
        objname = str(objname)
        self.lock.acquire()
        o = self.objects.get(objname, None)
        if o:
            o[1] -= 1
        if o[1] <= 0:
            del self.objects[objname]
        self.lock.release()

    def getShared(self, objname, trylock=False):
        o = self.getObj(objname)
        r = o[0].rlock(blocking=(not trylock))
        if not r:
            self.putObj(objname)
        return r

    def getExclusive(self, objname, trylock=False):
        o = self.getObj(objname)
        r = o[0].wlock(blocking=(not trylock))
        if not r:
            self.putObj(objname)
        return r

    def release(self, objname, exclusive=False):
        o = self.getObj(objname)
        if exclusive:
            o[0].wunlock()
        else:
            o[0].runlock()
        self.putObj(objname)

    def acquire(self, objname, exclusive=False, trylock=False):
        if exclusive:
            return self.getExclusive(objname, trylock=trylock)
        else:
            return self.getShared(objname, trylock=trylock)
